package ferp.center.server.backend;

import ferp.center.server.Action;
import ferp.center.server.entity.Range;
import ferp.center.server.entity.Rating;
import ferp.center.server.ranking.Lookup;
import ferp.center.server.task.TaskRangeTreeRemoveLeaf;

import javax.persistence.EntityManager;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

/**
 * User: olegs
 * Date: 3/6/13 10:43 PM
 */
public class RangeTreeMaintenance extends HttpServlet
{
  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
  {
    Action.queueTaskForBackend(response, "RT maintenance", "/rt/maintenance");
  }

  protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
  {
    Action.execute(request, new Action.Task()
    {
      @SuppressWarnings("unchecked")
      public void run(EntityManager em, HttpServletRequest request) throws IOException
      {
        removeEmptyLeaves(em);
      }
    });
  }

  private static final int CHUNK_SIZE = 1000;
  @SuppressWarnings("unchecked")
  private static List<Range> leaves(EntityManager em, int offset) {return em.createQuery("SELECT r FROM Range r WHERE r.level=0").setMaxResults(CHUNK_SIZE).setFirstResult(offset).getResultList();}

  private void removeEmptyLeaves(EntityManager em)
  {
    long empty = 0;

    log("looking for empty RT leaves...");

    try
    {
      int offset = 0;

      for (List<Range> leaves = leaves(em, offset); leaves.size() > 0; offset += leaves.size(), leaves = leaves(em, offset))
        for (Range leaf : leaves)
        {
          List<Rating> ratings = Lookup.ratings(em, leaf);

          if (ratings.size() == 0)
          {
            ++empty;
            // queue empty leaf for removal
            TaskRangeTreeRemoveLeaf.queue(leaf);
          }
        }
    }
    finally
    {
      log("empty leaves found: " + empty);
    }
  }
}
